package com.alvis.media.service.impl;

import com.alvis.media.utility.PythonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeoutException;

/**
 * Python模型训练服务
 * 用于调用机器学习训练Python脚本
 * @author
 */
@Service
public class PythonModelTrainingService {

    private static final Logger logger = LoggerFactory.getLogger(PythonModelTrainingService.class);
    
    // Python解释器路径 - 根据实际环境修改
    private final String pythonPath = "python";
    
    // 训练脚本路径
    private final String trainingScriptPath = "src/main/resources/python_scripts/xunlian.py";
    
    /**
     * 执行模型训练
     * @param csvFilePath CSV数据文件路径
     * @return 训练结果
     */
    public String trainModel(String csvFilePath) {
        logger.info("开始执行机器学习模型训练...");
        logger.info("数据文件: {}", csvFilePath);
        logger.info("训练脚本: {}", trainingScriptPath);
        
        try {
            // 检查必要的文件是否存在
            if (!checkFileExists(csvFilePath)) {
                String errorMsg = "CSV数据文件不存在: " + csvFilePath;
                logger.error(errorMsg);
                return errorMsg;
            }
            
            if (!checkFileExists(trainingScriptPath)) {
                String errorMsg = "训练脚本不存在: " + trainingScriptPath;
                logger.error(errorMsg);
                return errorMsg;
            }
            
            // 创建参数列表
            List<String> args = new ArrayList<>();
            // 可以根据需要添加额外的参数
            args.add(csvFilePath);
            
            // 执行Python脚本
            logger.info("开始调用Python脚本进行训练...");
            String result = PythonUtil.executeScript(pythonPath, trainingScriptPath, args);
            
            logger.info("模型训练完成，结果: {}", result);
            return result;
            
        } catch (IOException e) {
            String errorMsg = "执行Python脚本时发生IO异常: " + e.getMessage();
            logger.error(errorMsg, e);
            return errorMsg;
        } catch (InterruptedException e) {
            String errorMsg = "执行Python脚本时被中断: " + e.getMessage();
            logger.error(errorMsg, e);
            Thread.currentThread().interrupt();
            return errorMsg;
        } catch (Exception e) {
            String errorMsg = "执行模型训练时发生异常: " + e.getMessage();
            logger.error(errorMsg, e);
            return errorMsg;
        }
    }
    
    /**
     * 执行模型训练（带超时设置）
     * @param csvFilePath CSV数据文件路径
     * @param timeoutSeconds 超时时间（秒）
     * @return 训练结果
     */
    public String trainModelWithTimeout(String csvFilePath, long timeoutSeconds) {
        logger.info("开始执行机器学习模型训练（超时设置: {}秒）...", timeoutSeconds);
        logger.info("数据文件: {}", csvFilePath);
        
        try {
            // 检查必要的文件是否存在
            if (!checkFileExists(csvFilePath)) {
                String errorMsg = "CSV数据文件不存在: " + csvFilePath;
                logger.error(errorMsg);
                return errorMsg;
            }
            
            // 创建参数列表
            List<String> args = new ArrayList<>();
            args.add(csvFilePath);
            
            // 执行Python脚本并设置超时
            logger.info("开始调用Python脚本进行训练...");
            String result = PythonUtil.executeScriptWithTimeout(pythonPath, trainingScriptPath, args, timeoutSeconds);
            
            logger.info("模型训练完成，结果: {}", result);
            return result;
            
        } catch (TimeoutException e) {
            String errorMsg = "模型训练超时（超过" + timeoutSeconds + "秒）";
            logger.error(errorMsg, e);
            return errorMsg;
        } catch (Exception e) {
            String errorMsg = "执行超时训练时发生异常: " + e.getMessage();
            logger.error(errorMsg, e);
            return errorMsg;
        }
    }
    
    /**
     * 准备示例数据并执行训练
     * 适用于测试或演示场景
     * @return 训练结果
     */
    public String trainModelWithExampleData() {
        logger.info("准备示例数据并执行模型训练...");
        
        try {
            // 创建示例CSV数据文件
            String exampleCsvPath = createExampleCsvFile();
            logger.info("创建示例数据文件: {}", exampleCsvPath);
            
            // 执行训练
            return trainModel(exampleCsvPath);
            
        } catch (Exception e) {
            String errorMsg = "准备示例数据并执行训练时发生异常: " + e.getMessage();
            logger.error(errorMsg, e);
            return errorMsg;
        }
    }
    
    /**
     * 获取训练生成的图表文件列表
     * @return 图表文件列表
     */
    public List<String> getTrainingCharts() {
        logger.info("获取训练生成的图表文件...");
        
        try {
            // 训练脚本应该在当前目录生成图表文件
            File currentDir = new File(".");
            String[] chartFiles = currentDir.list((dir, name) -> {
                return name.endsWith(".png") && 
                       (name.contains("model_performance") || 
                        name.contains("prediction") || 
                        name.contains("feature_importance") || 
                        name.contains("distribution") || 
                        name.contains("correlation"));
            });
            
            if (chartFiles != null) {
                return Arrays.asList(chartFiles);
            } else {
                return new ArrayList<>();
            }
            
        } catch (Exception e) {
            logger.error("获取图表文件列表时发生异常: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 检查文件是否存在
     * @param filePath 文件路径
     * @return 是否存在
     */
    private boolean checkFileExists(String filePath) {
        File file = new File(filePath);
        return file.exists() && file.isFile();
    }
    
    /**
     * 创建示例CSV数据文件
     * 生成符合训练脚本要求的模拟数据
     * @return CSV文件路径
     * @throws IOException IO异常
     */
    private String createExampleCsvFile() throws IOException {
        // 创建文件路径
        String csvPath = "tmdb_credits_cleaned.csv";
        Path path = Paths.get(csvPath);
        
        // 创建示例数据内容
        StringBuilder csvContent = new StringBuilder();
        csvContent.append("cast_size,crew_size,total_team_size,num_top_actors,num_writers,has_female_actor,director,writers,cast,vote_average\n");
        
        // 生成100条模拟数据
        for (int i = 0; i < 100; i++) {
            int castSize = 5 + (i % 20);
            int crewSize = 20 + (i % 30);
            int totalTeamSize = castSize + crewSize;
            int numTopActors = 1 + (i % 5);
            int numWriters = 1 + (i % 3);
            int hasFemaleActor = i % 2;
            String director = i % 5 == 0 ? "James Cameron" : (i % 5 == 1 ? "Christopher Nolan" : "Other Director");
            String writers = "['Writer 1', 'Writer 2']";
            String cast = "[{'gender': 2}, {'gender': " + (hasFemaleActor == 1 ? "1" : "2") + "}, {'gender': 2}]";
            double voteAverage = 5.0 + (Math.random() * 5.0);
            
            csvContent.append(String.format("%d,%d,%d,%d,%d,%d,%s,%s,%s,%.2f\n",
                    castSize, crewSize, totalTeamSize, numTopActors, numWriters, 
                    hasFemaleActor, director, writers, cast, voteAverage));
        }
        
        // 写入文件
        try {
            Files.write(path, csvContent.toString().getBytes(StandardCharsets.UTF_8));
        } catch (IOException e) {
            logger.error("写入示例CSV文件失败", e);
            throw e;
        }
        logger.info("成功创建示例CSV数据文件，共{}条记录", 100);
        
        return csvPath;
    }
    
    /**
     * 检查Python环境
     * @return 环境检查结果
     */
    public String checkPythonEnvironment() {
        logger.info("检查Python环境...");
        
        try {
            boolean isAvailable = PythonUtil.checkPythonEnvironment(pythonPath);
            
            if (isAvailable) {
                String version = PythonUtil.getPythonVersion(pythonPath);
                String result = "Python环境正常可用";
                if (version != null) {
                    result += ", 版本: " + version;
                }
                logger.info(result);
                return result;
            } else {
                String errorMsg = "Python环境不可用，请检查Python是否正确安装且在PATH中";
                logger.error(errorMsg);
                return errorMsg;
            }
            
        } catch (Exception e) {
            String errorMsg = "检查Python环境时发生异常: " + e.getMessage();
            logger.error(errorMsg, e);
            return errorMsg;
        }
    }
}